package com.akaovi.chatroom.process;


import com.akaovi.chatroom.mess.*;
import com.akaovi.chatroom.scene.ChatList;
import com.akaovi.chatroom.scene.FriendsList;
import com.akaovi.chatroom.utils.CommonUtils;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Optional;
import java.util.function.Predicate;

/**
 * @author akaovi
 * @version 1.0
 * @description 用户线程
 * @date 2022/12/7 17:37
 * @since 2022/12/7 17:37
 */
public class OwnThread implements Runnable {
    Socket socket;
    ObjectInputStream ois;
    ObjectOutputStream oos;
    int account;
    public boolean isOnline;

    public OwnThread(Socket socket, ObjectInputStream ois, ObjectOutputStream oos, int account) {
        this.socket = socket;
        this.ois = ois;
        this.oos = oos;
        this.account = account;
        this.isOnline = true;
    }

    @Override
    public void run() {
        try {
            while (isOnline) {
                Message mess = (Message) ois.readObject();
                dispatcher(mess);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            CommonUtils.closeResource(socket, oos, ois);
        }
    }

    /**
     * 消息处理器
     *
     * @param mess 基础消息体
     */
    private void dispatcher(Message mess) {
        if (mess.type == MessType.AcceptMess) {
            acceptMess((AcceptMess) mess);
        } else if (mess.type == MessType.OfflineMess) {
            // 刪除下线的人
            ChatList.removeOne(String.valueOf(((OnOrOffLineMess) mess).account));
        } else if (mess.type == MessType.FriendsMess) {
            handleFriendsMess((FriendsMess) mess);
        } else if (mess.type == MessType.OnlineMess) {
            handleOnlineMess((OnOrOffLineMess) mess);
        } else if (mess.type == MessType.AgreeAddFriend) {
            handleAgreeAddFriend((AddOrDeleteFriend) mess);
        } else if (mess.type == MessType.AddFriend) {
            handleAddFriend((AddOrDeleteFriend) mess);
        } else {
            System.out.println("无法识别");
        }
    }

    /**
     * 处理同意添加好友信息
     * @param mess
     */
    private void handleAgreeAddFriend(AddOrDeleteFriend mess) {
        Platform.runLater(() -> {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("成功添加好友");
            alert.setContentText(String.format("成功添加好友 %s", mess.account));

            alert.showAndWait();
        });
    }

    /**
     * 处理添加好友信息
     * @param mess
     */
    private void handleAddFriend(AddOrDeleteFriend mess) {
        Platform.runLater(() -> {
            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            alert.setTitle("添加好友");
            alert.setContentText(String.format("是否同意 %s 加你为好友", mess.from));

            Optional<ButtonType> result = alert.showAndWait();
            if (result.isPresent() && result.get() == ButtonType.OK) {
                // 同意
                try {
                    mess.type = MessType.AgreeAddFriend;
                    oos.writeObject(mess);
                    oos.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 处理上线信息
     * @param mess
     */
    private void handleOnlineMess(OnOrOffLineMess mess) {
        Optional<Node> first = ChatList.chatList.getChildren().stream().filter((new Predicate<Node>() {
            @Override
            public boolean test(Node node) {
                Label l = (Label) node;
                return l.getId().equals(String.valueOf(mess.account));
            }
        })).findFirst();
        if (first.isPresent()) {
            return;
        }
        // 可以在服务器优化  但是没必要
        for (Node child : FriendsList.friendsList.getChildren()) {
            if (child.getId().equals(String.valueOf(mess.account))) {
                ChatList.addFriendToChatList(mess.account, ((Label) child).getText());
            }
        }
    }

    /**
     * 处理好友与其在线状态的信息
     * @param mess
     */
    private void handleFriendsMess(FriendsMess mess) {
        for (int i = 0; i < mess.isOnline.length; i++) {
            if (mess.isOnline[i] && account != mess.accounts[i]) {
                // 在线
                ChatList.addFriendToChatList(mess.accounts[i], (String) mess.usernames[i]);
            }
            FriendsList.addFriendToFriendsList(mess.accounts[i], (String) mess.usernames[i]);
        }
    }

    /**
     * 接收消息
     *
     * @param mess 消息本体
     */
    private void acceptMess(AcceptMess mess) {
        Optional<Node> first = ChatList.chatList.getChildren().stream().filter((new Predicate<Node>() {
            @Override
            public boolean test(Node node) {
                Label l = (Label) node;
                return l.getId().equals(String.valueOf(mess.account));
            }
        })).findFirst();
        // 好友一定查得到
        Label l = (Label) first.get();
        ChatMessManage.add(String.format("%s: %s", l.getText(), mess.data));
    }

    /**
     * 发送消息
     *
     * @param text 待发送消息内容
     * @param to   对方账号
     */
    public void sendMess(String text, int to) {
        try {
            oos.writeObject(new SendMess(MessType.SendMess, account, to, text));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加好友
     *
     * @param account 对方账号
     */
    public void sendToAddFriend(String account, String msg) {
        try {
            oos.writeObject(new AddOrDeleteFriend(MessType.AddFriend, String.valueOf(this.account), account, msg));
            oos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除好友
     *
     * @param account 对方账号
     */
    public void sendToDeleteFriend(String account) {
        try {
            oos.writeObject(new AddOrDeleteFriend(MessType.DeleteFriend, String.valueOf(this.account), account, null));
            oos.flush();
            // todo
            // 删除展示中的好友
            // 在场景写
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 告知服务端下线，并关闭线程
     */
    public void close() {
        try {
            oos.writeObject(new Logout(MessType.Logout, account));
            oos.flush();
            isOnline = false;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
